/* 
 * Copyright (C) 2012 UTSChedule
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package utsc.apps.utschedule.ui.activities;

import java.util.Calendar;
import utsc.apps.utschedule.R;
import utsc.apps.utschedule.classes.Assignment;
import utsc.apps.utschedule.classes.Course;
import utsc.apps.utschedule.services.ReminderClient;
import utsc.apps.utschedule.ui.MessageDialogFragment;
import utsc.apps.utschedule.ui.interfaces.TimetableActivity;
import utsc.apps.utschedule.util.AppUtils;
import utsc.apps.utschedule.util.GenericActionModeCallback;
import utsc.apps.utschedule.util.TimetableHelper;
import utsc.apps.utschedule.util.Validator;
import utsc.apps.utschedule.util.database.DatabaseManager;
import android.app.Activity;
import android.app.DatePickerDialog.OnDateSetListener;
import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.format.Time;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TimePicker;
import android.widget.Toast;

import com.actionbarsherlock.view.ActionMode;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;

/**
 * This a form activity to perform the CRU (D is performed in the detail view) operation of an {@link utsc.apps.utschedule.classes.Assignment Assignment}.
 *
 */
public class AssignmentFormActivity extends GenericFormActivity<Assignment> implements GenericActionModeCallback.OnMenuItemClickedListener, OnDateSetListener, OnTimeSetListener, OnClickListener, TextWatcher {

	/**
	 * This is a helper client to setup the reminder.
	 */
	private ReminderClient _reminderClient;
	private EditText _txtDesc;
	private EditText _txtTitle;
	private EditText _txtDueDate;
	private EditText _txtDueTime;
	private EditText _txtWeight;
	private EditText _txtReminder;
	private Spinner _spinnerReminderUnit;
	
	private Assignment _assignment;
	public static final String TAG="utsc.apps.utschedule.ui.activities.AssignmentFormActivity";

	private EditText _currentEditingDateView;
	private EditText _currentEditingTimeView;
	private final Validator _validator=Validator.newInstance(TAG);
	private EditText _txtMark;
	private EditText _txtTotal;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		Intent requestIntent=getIntent();
		if (requestIntent!=null) {
			_requestCode=requestIntent.getIntExtra("RequestCode", TimetableActivity.RESULT_NEW_ASSIGNMENT);
		}
		setContentView(R.layout.activity_create_assignment_form);
		setupBasicResources();
		if (_requestCode==TimetableActivity.RESULT_NEW_ASSIGNMENT) {
			setupResourcesForNew(requestIntent);
		}else {
			setupResourcesForUpdate(requestIntent);
		}
		getSupportActionBar().setDisplayHomeAsUpEnabled(true);
		_reminderClient=new ReminderClient(this);
		_reminderClient.doBindService();
	}
	
	@Override
	protected void onStop() {
		//unbind the reminder client
		if (_reminderClient!=null) {
			_reminderClient.doUnbindService();
			_reminderClient=null;
		}
		super.onStop();
	}
	
	@Override
	protected void setupBasicResources() {
		setContentView(R.layout.activity_create_assignment_form);
		_txtTitle=(EditText) findViewById(R.id.frm_txt_title);
		_txtDesc=(EditText) findViewById(R.id.frm_txt_desc);
		_txtWeight=(EditText) findViewById(R.id.frm_txt_weight);
		_txtDueDate=(EditText) findViewById(R.id.frm_txt_dueDate);
		_txtDueTime=(EditText) findViewById(R.id.frm_txt_dueTime);
		_txtReminder=(EditText) findViewById(R.id.frm_txt_alarm);
		_txtMark=(EditText) findViewById(R.id.frm_txt_mark);
		_txtTotal=(EditText) findViewById(R.id.frm_txt_total);
		_spinnerReminderUnit=(Spinner) findViewById(R.id.frm_spinner_alarm_unit);
		_txtDueDate.setOnClickListener(this);
		_txtDueTime.setOnClickListener(this);
		_txtDueDate.addTextChangedListener(this);
	}
	
	@Override
	protected void setupResourcesForNew(Intent requestIntent){
		final Object savedData=getLastCustomNonConfigurationInstance();
		String defaultDueDate=TimetableHelper.getFormattedString(System.currentTimeMillis(), TimetableHelper.TYPE_DATE);
		String defaultDueTime=TimetableHelper.getHourString(0,0);
		SharedPreferences preferences=PreferenceManager.getDefaultSharedPreferences(this);
		String defaultReminder=preferences.getString("reminder_time", "1");
		String defaultWeight="0";
		if (savedData!=null) {
			//final Bundle b=(Bundle) savedData;
			//defaultDueDate=b.getString(SELECTED_STARTTIME_KEY);
			//defaultDueTime=b.getString(SELECTED_ENDTIME_KEY);
		}
		
		_txtDueDate.setText(defaultDueDate);
		_txtDueTime.setText(defaultDueTime);
		_txtReminder.setText(defaultReminder);
		_txtWeight.setText(defaultWeight);
		_spinnerReminderUnit.setSelection(Integer.parseInt(preferences.getString("reminder_unit", "1")));
		
	}
	
	/**
	 * Shows a {@link utsc.apps.utschedule.ui.MyTimePickerDialogFragment TimePickerDialog}
	 * @param textView the associated {@link EditText}
	 */
	private void onEditTime(EditText textView){
		_currentEditingTimeView=textView;
		AppUtils.hideKeyBoard(AssignmentFormActivity.this, textView);
		final Calendar currentTimeSelection=TimetableHelper.convertFromDateTimeString(textView.getText().toString(), TimetableHelper.TYPE_TIME);
		if (currentTimeSelection!=null) {
			showTimePickerDialog(currentTimeSelection, false, this);
		}
	}
	
	/**
	 * Shows a {@link utsc.apps.utschedule.ui.MyDatePickerDialogFragment DatePickerDialog}
	 * @param textView the associated {@link EditText}
	 */
	private void onEditDate(EditText textView){
		_currentEditingDateView=textView;
		AppUtils.hideKeyBoard(AssignmentFormActivity.this, textView);
		final Calendar currentDateSelection=TimetableHelper.convertFromDateTimeString(textView.getText().toString(), TimetableHelper.TYPE_DATE);
		if (currentDateSelection!=null) {
			showDatePickerDialog(currentDateSelection, false, this);
		}
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		if (_requestCode==TimetableActivity.RESULT_NEW_ASSIGNMENT) {
			getSupportMenuInflater().inflate(R.menu.add_cancel_menu, menu);
		}else {
			getSupportMenuInflater().inflate(R.menu.update_cancel_menu_items, menu);
		}
		
		return true;
	}

	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		onMenuItemClicked(item);
		return true;
	}
	
	@Override
	public void onActionModeFinished(ActionMode mode) {
		super.onActionModeFinished(mode);
		setResult(Activity.RESULT_CANCELED);
		finish();
	}
	
	@Override
	public void onMenuItemClicked(MenuItem item) {
		int courseId= getIntent().getIntExtra("CourseAssignment",-1);
		int itemID=item.getItemId();
		
		if (itemID!=R.id.cancel && itemID!=android.R.id.home) {
			//setup the assignment object from the view
			setupAssignment();
			//validate the input and perform further actions
			if (validate(_assignment)) {
				
				Intent resultIntent=new Intent();
				//based on different request {new or update}
				switch (_requestCode) {
					case TimetableActivity.RESULT_NEW_ASSIGNMENT:
						Course c=new Course();
						c.set_courseID(courseId);
						_assignment.set_course(c);
						Toast.makeText(this, AppUtils.TOAST_ADD_ASSIGNMENT_SUCCESSFULLY_STRING, Toast.LENGTH_SHORT).show();		
						break;
					default:
						Toast.makeText(this, AppUtils.TOAST_UPDATE_ASSIGNMENT_SUCCESSFULLY_STRING, Toast.LENGTH_SHORT).show();
						break;
				}
				//call the db manager to save the assignment or create it if not exist
				DatabaseManager dm = DatabaseManager.getInstance(this);
				dm.saveAssignment(_assignment);
				//we also setup the reminder if necessary
				setReminderAlarm();
				//next we always return the result course code back for result		
				resultIntent.putExtra("AssignmentCourseForResult", courseId);
				setResult(Activity.RESULT_OK, resultIntent);
				finish();
			}else {
				//we are here because we found some error, so we need to display an error message dialog
				String dialogTitle=_requestCode==TimetableActivity.RESULT_NEW_ASSIGNMENT?AppUtils.ERROR_TITLE_ASSIGNMENT_ADD:AppUtils.ERROR_TITLE_ASSIGNMENT_UPDATE;
				showDialogFragment(MessageDialogFragment.newInstance(dialogTitle, _validator.get_errorMessages()), MessageDialogFragment.TAG);
			}
		}else {
			//pop up a toast and do nothing if cancle or back
			if (_requestCode==TimetableActivity.RESULT_NEW_ASSIGNMENT) {
				Toast.makeText(this, AppUtils.TOAST_ADD_ASSIGNMENT_CANCELLED_STRING, Toast.LENGTH_SHORT).show();
			}else {
				Toast.makeText(this, AppUtils.TOAST_UPDATE_ASSIGNMENT_CANCELLED_STRING, Toast.LENGTH_SHORT).show();
			}
			finish();
		}
		
	}
	
	/**
	 * A setup method to setup a reminder according to different status.
	 */
	private void setReminderAlarm(){
		//combine the duedate and duetime to form a proper date time string for reminder
		String datetime=_assignment.get_DueDate()+" "+_assignment.get_DueTime();
		//parse the date time string
		Calendar calendar=TimetableHelper.convertFromDateTimeString(datetime, TimetableHelper.TYPE_DATETIME);
		calendar.add(Assignment.REMINDER_LIST[_assignment.get_reminderUnit()], -(_assignment.get_reminder()));
		//get the time in millis
		long d=calendar.getTimeInMillis();
		boolean setReminderAlarm=true;
		
		if (_assignment.is_expired()) {
			Time now=new Time();
			now.setToNow();
			now.second=0;
			now.normalize(false);
			
			Time t=new Time();
			t.set(d);
			//we only concern about the reminder as if the new reminder setting is later than the current time
			//otherwise ignore the reminder setup
			if (!t.after(now)) {
				setReminderAlarm=false;
			}
		}
		if (setReminderAlarm) {
			_reminderClient.setAlarmForNotification(d,"assignment:"+_assignment.get_AssUID());
		}
	}
	
	@Override
	public void onDateSet(DatePicker view, int year, int monthOfYear,
			int dayOfMonth) {
		Calendar cal = Calendar.getInstance();
		cal.set(year, monthOfYear, dayOfMonth);
		String selectedDate = TimetableHelper.getFormattedString(cal.getTimeInMillis(), TimetableHelper.TYPE_DATE);
		_currentEditingDateView.setText(selectedDate);
	}
	
	@Override
	public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
		view.setCurrentHour(hourOfDay);
		view.setCurrentMinute(minute);
		_currentEditingTimeView.setText(TimetableHelper.getHourString(hourOfDay, minute));
	}
	
	@Override
	public Object onRetainCustomNonConfigurationInstance() {
		Bundle b=new Bundle();
		//TODO: should we save the input state?
		//b.putString(Assignment.DUEDATE, _txtDueDate.getText().toString());
		//b.putString(Assignment.DUETIME, _txtDueTime.getText().toString());
		
		return b;
	}
	
	@Override
	public void onClick(View v) {
		int id=v.getId();
		switch (id) {
		case R.id.frm_txt_dueDate:
			onEditDate(_txtDueDate);
			break;
		case R.id.frm_txt_dueTime:
			onEditTime(_txtDueTime);
			break;
		default:
			break;
		}
	}

	@Override
	protected boolean validate(Assignment object) {
		_validator.reset();
		
		_validator.checkNull(object.get_Title(), AppUtils.ERROR_MESSAGE_ASSIGNMENT_TITLE);
		_validator.checkZeroNum(object.get_weight(), AppUtils.ERROR_MESSAGE_ASSIGNMENT_WEIGHT);
		
		if (_requestCode==TimetableActivity.RESULT_UPDATE_ASSIGNMENT && object.is_expired()) {
			_validator.checkDecimalMinMax(object.get_mark(), object.get_total(), AppUtils.ERROR_MESSAGE_GENERIC_TOTAL_LESS);
		}
		if (_validator.get_errorMessages()==null) {
			return true;
		}
		return false;
	}
	
	/**
	 * Sets up the {@link Assignment assignment} object by reading the data from the form.
	 */
	private void setupAssignment(){
		if (_requestCode==TimetableActivity.RESULT_UPDATE_ASSIGNMENT) {
			Intent requestIntent=getIntent();
			if (requestIntent!=null) {
				//we only set the mark and total if we are updating the assignment
				_assignment=new Assignment(requestIntent);
				_assignment.set_mark(Double.parseDouble(_txtMark.getText().toString()));
				_assignment.set_total(Double.parseDouble(_txtTotal.getText().toString()));
			}
		}else {
			_assignment=new Assignment();
		}
		_assignment.set_Title(_txtTitle.getText().toString());
		_assignment.set_description(_txtDesc.getText().toString());
		_assignment.set_weight(Double.parseDouble(_txtWeight.getText().toString()));
		_assignment.set_DueDate(_txtDueDate.getText().toString());
		_assignment.set_DueTime(_txtDueTime.getText().toString());
		_assignment.set_reminder(Integer.parseInt(_txtReminder.getText().toString()));
		_assignment.set_reminderUnit(_spinnerReminderUnit.getSelectedItemPosition());
	}
	
	@Override
	protected void setupResourcesForUpdate(Intent requestIntent) {
		final Object savedData=getLastCustomNonConfigurationInstance();
		String defaultDueDate = null;
		String defaultDueTime=null;
		String defaultReminder="1";
		String defaultWeight="0";
		String defaultDesc=null;
		String defaultTitle=null;
		String defaultMark=null;
		String defaultTotal=null;
		int defaultReminderUnitPos=1;
		
		if (savedData!=null) {
			//final Bundle b=(Bundle) savedData;
		}else {
			 defaultDueDate=requestIntent.getStringExtra(Assignment.DUEDATE);//TimetableHelper.getFormattedString(System.currentTimeMillis(), TimetableHelper.TYPE_DATE);
			 defaultDueTime=requestIntent.getStringExtra(Assignment.DUETIME);//TimetableHelper.getHourString(0,0);
			 defaultReminder=Integer.toString(requestIntent.getIntExtra(Assignment.REMINDER,1));
			 defaultWeight=Double.toString(requestIntent.getDoubleExtra(Assignment.WEIGHT,0));
			 defaultReminderUnitPos=requestIntent.getIntExtra(Assignment.REMINDERUNIT, 1);
			 defaultDesc=requestIntent.getStringExtra(Assignment.DESCRIPTION);
			 defaultTitle=requestIntent.getStringExtra(Assignment.TITLE);
			 defaultMark=Double.toString(requestIntent.getDoubleExtra(Assignment.MARK, 0));
			 defaultTotal=Double.toString(requestIntent.getDoubleExtra(Assignment.TOTAL, 0));
			 
			 if (requestIntent.getBooleanExtra(Assignment.EXPIRED, false)) {
				findViewById(R.id.frm_grade).setVisibility(View.VISIBLE);
			 }
		}
		_txtTitle.setText(defaultTitle);
		_txtDesc.setText(defaultDesc);
		_txtDueDate.setText(defaultDueDate);
		_txtDueTime.setText(defaultDueTime);
		_txtReminder.setText(defaultReminder);
		_txtWeight.setText(defaultWeight);
		_spinnerReminderUnit.setSelection(defaultReminderUnitPos);
		_txtMark.setText(defaultMark);
		_txtTotal.setText(defaultTotal);
	}
	
	
	@Override
	public void onTextChanged(CharSequence s, int start, int before, int count) {
	}
	
	@Override
	public void beforeTextChanged(CharSequence s, int start, int count, int after) {
	}
	
	@Override
	public void afterTextChanged(Editable s) {
	}
}
